﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using Moq;
using NUnit.Framework;
using CollectionAssert = Microsoft.VisualStudio.TestTools.UnitTesting.CollectionAssert;

namespace AsyncLoggers.Tests
{
    [TestFixture]
    public class AsyncTraceListenerTests
    {
        private static IEnumerable TraceListenerOperations
        {
            get
            {
                return new Action<AsyncTraceListener>[]
                           {
                               l => l.Flush(),
                               l => l.Dispose()
                           };
            }
        }

        [TestCaseSource("TraceListenerOperations")]
        [Test]
        public void MakeSureAllMessagesAreBeingLogged(Action<AsyncTraceListener> action)
        {
            var listnereMock = new Mock<TraceListener>();
            var listener = new AsyncTraceListener(listnereMock.Object);

            var expected = new List<string> { "message1", "message2", "message3" };
            var actual = new List<string>();

            listnereMock.Setup(m => m.Write(It.IsAny<string>())).Callback((string i) => actual.Add(i));

            expected.ForEach(listener.Write);

            action.Invoke(listener);

            CollectionAssert.AreEqual(expected, actual);
        }

        [Test]
        public void TestYouCannotDoJackAfterObjectHasBeenDisposed()
        {
            var listnereMock = new Mock<TraceListener>();
            var listener = new AsyncTraceListener(listnereMock.Object);

            listener.Dispose();

            DisposablePatternTester.MakeSureDisposedObjectIsUnusable(listener);
        }

        [Test]
        public void MakeSureLoggerDoesCaptureAllMessagesItGetsBigVolume()
        {
            int numberOfLoggedMessages = 0;

            var listnereMock = new Mock<TraceListener>();
            listnereMock.Setup(m => m.Write(It.IsAny<string>())).Callback((string i) => numberOfLoggedMessages++);

            var listener = new AsyncTraceListener(listnereMock.Object);

            const int numberOfMessagesToLog = 1000;

            for (int i = 0; i < numberOfMessagesToLog; i++)
            {
                listener.Write("123");

                if (i % 10 == 0)
                {
                    Thread.Sleep(5);
                }
            }

            listener.Flush();

            Assert.AreEqual(numberOfMessagesToLog, numberOfLoggedMessages);
        }
    }
}